package com.muyu.payment.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.muyu.payment.domain.BalanceTransaction;
import com.muyu.payment.domain.UserBalance;
import com.muyu.payment.mapper.BalanceTransactionMapper;
import com.muyu.payment.mapper.UserBalanceMapper;
import com.muyu.payment.service.UserBalanceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;

/**
 * 用户余额服务实现类
 *
 * @author muyu
 * @date 2025-01-27
 */
@Slf4j
@Service
public class UserBalanceServiceImpl extends ServiceImpl<UserBalanceMapper, UserBalance> implements UserBalanceService {

    @Autowired
    private UserBalanceMapper userBalanceMapper;

    @Autowired
    private BalanceTransactionMapper balanceTransactionMapper;

    @Override
    public UserBalance getBalanceByUserId(Long userId) {
        return userBalanceMapper.selectByUserId(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserBalance initUserBalance(Long userId, String userName) {
        UserBalance userBalance = UserBalance.builder()
                .userId(userId)
                .userName(userName)
                .balance(BigDecimal.ZERO)
                .version(0)
                .status(0)
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        
        save(userBalance);
        log.info("初始化用户余额成功，用户ID: {}, 用户名: {}", userId, userName);
        return userBalance;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean increaseBalance(Long userId, BigDecimal amount, Integer transactionType, String orderNo, String description) {
        try {
            UserBalance userBalance = getBalanceByUserId(userId);
            if (userBalance == null) {
                log.error("用户余额不存在，用户ID: {}", userId);
                return false;
            }

            // 使用乐观锁更新余额
            int result = userBalanceMapper.increaseBalance(userId, amount, userBalance.getVersion());
            if (result == 0) {
                log.error("更新用户余额失败，可能存在并发操作，用户ID: {}", userId);
                return false;
            }

            // 记录余额变动
            recordBalanceTransaction(userId, userBalance.getUserName(), transactionType, amount, 
                    userBalance.getBalance(), userBalance.getBalance().add(amount), 
                    orderNo, 1, description);

            log.info("增加用户余额成功，用户ID: {}, 金额: {}", userId, amount);
            return true;
        } catch (Exception e) {
            log.error("增加用户余额失败，用户ID: {}, 金额: {}", userId, amount, e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean decreaseBalance(Long userId, BigDecimal amount, Integer transactionType, String orderNo, String description) {
        try {
            UserBalance userBalance = getBalanceByUserId(userId);
            if (userBalance == null) {
                log.error("用户余额不存在，用户ID: {}", userId);
                return false;
            }

            // 检查余额是否充足
            if (userBalance.getBalance().compareTo(amount) < 0) {
                log.error("用户余额不足，用户ID: {}, 可用余额: {}, 需要金额: {}", 
                        userId, userBalance.getBalance(), amount);
                return false;
            }

            // 使用乐观锁更新余额
            int result = userBalanceMapper.decreaseBalance(userId, amount, userBalance.getVersion());
            if (result == 0) {
                log.error("更新用户余额失败，可能存在并发操作或余额不足，用户ID: {}", userId);
                return false;
            }

            // 记录余额变动
            recordBalanceTransaction(userId, userBalance.getUserName(), transactionType, amount, 
                    userBalance.getBalance(), userBalance.getBalance().subtract(amount), 
                    orderNo, 1, description);

            log.info("减少用户余额成功，用户ID: {}, 金额: {}", userId, amount);
            return true;
        } catch (Exception e) {
            log.error("减少用户余额失败，用户ID: {}, 金额: {}", userId, amount, e);
            throw e;
        }
    }


    @Override
    public boolean checkBalanceSufficient(Long userId, BigDecimal amount) {
        UserBalance userBalance = getBalanceByUserId(userId);
        if (userBalance == null) {
            return false;
        }
        return userBalance.getBalance().compareTo(amount) >= 0;
    }

    /**
     * 记录余额变动
     */
    private void recordBalanceTransaction(Long userId, String userName, Integer transactionType, 
                                        BigDecimal amount, BigDecimal beforeBalance, BigDecimal afterBalance,
                                        String orderNo, Integer status, String description) {
        BalanceTransaction transaction = BalanceTransaction.builder()
                .transactionNo("BT" + IdUtil.simpleUUID())
                .userId(userId)
                .userName(userName)
                .transactionType(transactionType)
                .amount(amount)
                .beforeBalance(beforeBalance)
                .afterBalance(afterBalance)
                .orderNo(orderNo)
                .status(status)
                .description(description)
                .transactionTime(new Date())
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        
        balanceTransactionMapper.insert(transaction);
    }
}